/*
 * Copyright (c) 2021
 * User:魔金多商户商城
 * File:OssServiceImpl.java
 * Date:2020/09/13 08:43:13
 */

package com.ruoyi.setting.service.impl;


import com.google.gson.Gson;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.EQiNiuArea;
import com.ruoyi.common.md5.MD5;
import com.ruoyi.common.utils.YunUploadUtils;
import com.ruoyi.common.utils.bean.OssSetting;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.setting.bean.UploadData;
import com.ruoyi.setting.mapper.OssMapper;
import com.ruoyi.setting.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;


/**
 * Created by luozhuo on 2020/7/7.
 * 云存储服务实现类
 */
@Slf4j
@Service
public class OssServiceImpl implements OssService {

    private Logger logger = LoggerFactory.getLogger(OssServiceImpl.class);

    @Autowired
    private OssMapper ossMapper;

    @Override
    public List<String> uploadToQqOss(List<UploadData> uploadDatas) {
        logger.debug("Begin to uploadToQqOss....");
        if (CollectionUtils.isEmpty(uploadDatas)) {
            logger.error("uploadDatas fail  due to params is empty...");
            return Arrays.asList("");
        }
        return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance().uploadToQqOss(queryOssSetting().getUpYunConf(), uploadData.getMultipartFile(), uploadData.getDatas(), uploadData.getFileOriginName(), uploadData.getType())).collect(Collectors.toList());

    }

    @Override
    public List<String> uploadToQqOssForBase64(List<UploadData> uploadDatas) {
        if (CollectionUtils.isEmpty(uploadDatas)) {
            logger.error("uploadToQqOssForBase64 fail  due to params is empty...");
            return Arrays.asList("");
        }
        return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance().
                uploadToQqForBase64(queryOssSetting().getUpYunConf(), uploadData.getInputStream(), uploadData.getDatas(), uploadData.getFileOriginName())).collect(Collectors.toList());

    }

    @Override
    public List<String> uploadToOss(List<UploadData> uploadDatas) {
        logger.debug("Begin to uploadToOss....");
        if (CollectionUtils.isEmpty(uploadDatas)) {
            logger.error("uploadDatas fail  due to params is empty...");
            return Arrays.asList("");
        }
        return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance().uploadToOssYun(queryOssSetting().getUpYunConf(), uploadData.getInputStream(), uploadData.getDatas(), uploadData.getFileOriginName(), uploadData.getType())).collect(Collectors.toList());

    }

    @Override
    public List<String> uploadToOssForBase64(List<UploadData> uploadDatas) {
        if (CollectionUtils.isEmpty(uploadDatas)) {
            logger.error("uploadToOssForBase64 fail  due to params is empty...");
            return Arrays.asList("");
        }

        return uploadDatas.stream().filter(Objects::nonNull).map(uploadData -> YunUploadUtils.getInstance().
                uploadToQqForBase64(queryOssSetting().getUpYunConf(), uploadData.getInputStream(), uploadData.getDatas(), uploadData.getFileOriginName())).collect(Collectors.toList());

    }

    @Override
    public OssSetting queryOssSetting() {
        logger.debug("Begin to queryUpYunSetting....");
        return ossMapper.queryOssSetting();
    }

    @Override
    public int updateOss(OssSetting ossSetting) {
        logger.error("updateOss and OssSetting:{}", ossSetting);
        return ossMapper.updateOss(ossSetting);
    }

    @Override
    public String uploadToMinio(MultipartFile multipartFile, OssSetting ossSetting) {
        return YunUploadUtils.getInstance().uploadToMinio(multipartFile, ossSetting);
    }

    @Override
    public String upload(MultipartFile multipartFile) {
        OssSetting ossSetting = this.queryOssSetting();
        int i = Integer.parseInt(ossSetting.getPrefix()); //1 minio 2 qiniu 3 oss 4 qq云
        if (i == 1) {
            return this.uploadToMinio(multipartFile, ossSetting);
        } else if (i == 2) {
            return this.uploadToQiNiu(multipartFile, multipartFile.getName(), ossSetting);
        } else if (i == 3) {
            return this.uploadToOSSYun(multipartFile, multipartFile.getName(), ossSetting);
        } else if (i == 4) {
            return this.uploadToQqOSSYun(multipartFile, multipartFile.getName(), ossSetting);
        }
        log.error("upload:{}", i);
        return "";
    }

    @Override
    public String uploadToQiNiu(MultipartFile request, String name, OssSetting ossSetting) {
        BufferedOutputStream out = null;
        java.io.File dest = null;
        String url = "";
        try {
            //生成上传凭证，然后准备上传
            String accessKey = ossSetting.getAccessKeyId();
            String secretKey = ossSetting.getAccessKeySecret();
            String bucket = ossSetting.getBucketName();
            if (StringUtils.isEmpty(name)) {
                name = "image";
            }
            String oldName = request.getOriginalFilename();
            //获取扩展名，默认是jpg
            String picExpandedName = FileUtils.getPicExpandedName(oldName);
            //获取新文件名
            String newFileName = System.currentTimeMillis() + Constants.SYMBOL_POINT + picExpandedName;

            // 创建一个临时目录文件
            String tempFiles = "mojin/temp/" + newFileName;
            dest = new java.io.File(tempFiles);
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }

            out = new BufferedOutputStream(new FileOutputStream(dest));
            out.write(request.getBytes());
            out.flush();
            out.close();
            //构造一个带指定Zone对象的配置类
            Configuration cfg = setQiNiuArea("");

            //...其他参数参考类注释
            UploadManager uploadManager = new UploadManager(cfg);
            String key = UUID.randomUUID().toString();
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);
            Response response = uploadManager.put(dest, key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            log.info("{七牛图片上传key: " + putRet.key + ",七牛图片上传hash: " + putRet.hash + "}");
            return putRet.key;
        } catch (Exception e) {
            e.getStackTrace();
            log.error("文件上传七牛云失败: {}", e.getMessage());
        } finally {
            if (dest != null && dest.getParentFile().exists()) {
                dest.delete();
            }
        }
        return url;
    }

    @Override
    public String uploadToOSSYun(MultipartFile multipartFile, String name, OssSetting ossSetting) {
        try {
            if (StringUtils.isEmpty(name)) {
                name = "image";
            }
            return YunUploadUtils.getInstance().uploadFile2OSS(multipartFile.getInputStream(), multipartFile.getOriginalFilename(), ossSetting.getAccessKeyId(), ossSetting.getAccessKeySecret(), ossSetting.getBucketName(), ossSetting.getEndPoint(), null, null);

        } catch (Exception e) {

        }
        return null;
    }

    @Override
    public String uploadToQqOSSYun(MultipartFile multipartFile, String name, OssSetting ossSetting) {
        String url = null;

        String accessKey = ossSetting.getAccessKeyId();
        String secretKey = ossSetting.getAccessKeySecret();
        String bucket = ossSetting.getEndPoint();
        // bucket的命名规则为{name}-{appid} ，此处填写的存储桶名称必须为此格式
        String bucketName = ossSetting.getBucketName();
        // 1 初始化用户身份信息(secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey);
        // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(new Region(bucket));
        // 3 生成cos客户端
        COSClient cosclient = new COSClient(cred, clientConfig);
        //  String suffix = fileOriginName.substring(fileOriginName.lastIndexOf(".")).toLowerCase();
        //获取腾讯云路径前缀
        String dir = ossSetting.getPrefix();

        // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口
        // 大文件上传请参照 API 文档高级 API 上传
        File localFile = null;
        try {
            // 获取字符串的MD5结果，file.getBytes()--输入的字符串转换成字节数组
            String md5 = MD5.getMessageDigest(multipartFile.getBytes());
            String filePath = String.format("%1$s/%2$s%3$s", dir, md5, multipartFile.getOriginalFilename());
            localFile = File.createTempFile("temp", null);
            multipartFile.transferTo(localFile);
            // 指定要上传到 COS 上的路径
            String key = filePath;
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
            PutObjectResult putObjectResult = cosclient.putObject(putObjectRequest);
            String qCloudDomain = ossSetting.getAddress();
            url = String.format("%1$s/%2$s", qCloudDomain, filePath);

        } catch (IOException e) {

        } finally {
            // 关闭客户端(关闭后台线程)
            cosclient.shutdown();
        }

        return url;
    }

    /**
     * 设置七牛云上传区域（内部方法）
     *
     * @param area
     * @return
     */
    private Configuration setQiNiuArea(String area) {
        //构造一个带指定Zone对象的配置类
        Configuration cfg = null;

        //zong2() 代表华南地区
        switch (EQiNiuArea.valueOf(area).getCode()) {
            case "z0": {
                cfg = new Configuration(Zone.zone0());
            }
            break;
            case "z1": {
                cfg = new Configuration(Zone.zone1());
            }
            break;
            case "z2": {
                cfg = new Configuration(Zone.zone2());
            }
            break;
            case "na0": {
                cfg = new Configuration(Zone.zoneNa0());
            }
            break;
            case "as0": {
                cfg = new Configuration(Zone.zoneAs0());
            }
            break;
            default: {
                return null;
            }
        }
        return cfg;
    }
}
